#include "QROHost_P.h"

static void onParentChanged(QROHost::Private *_P,ObjectID target);
static QVariant packParentData(QROHost::Private* _P,ObjectID id);
static void dispatchParentImp(QROHost::Private* _P,ObjectID targetId,ObjectID parentId);

//对象父级监视器
class ParentObserver:public QtPrivate::QSlotObjectBase
{
public:
    ParentObserver():QtPrivate::QSlotObjectBase(&ParentObserver::FuncImpl){

    }
    static void FuncImpl(int which, QSlotObjectBase* this_, QObject *receiver, void **args, bool *ret){
        auto This = static_cast<ParentObserver*>(this_);

        if(which == QtPrivate::QSlotObjectBase::Operation::Call)
        {
            onParentChanged(This->_P,This->target);
        }
        else if(which == QtPrivate::QSlotObjectBase::Compare)
        {
            *ret = false;
        }
        else if(which == QtPrivate::QSlotObjectBase::Destroy)
        {
            delete This;
        }
    }

    QROHost::Private* _P;
    ObjectID target;
};

void QROHost::Private::observerParent(const QMetaObject* meta,ObjectData* data,QObject* target){
    auto roMeta = QRemoteObject2Meta::Instance()->fetchRemoteClass(meta->className());
    int signalIndex = roMeta->hierarchyInterface->parentNotifier(target);
    if(signalIndex == -1) return;
    auto slotObj = new ParentObserver();
    slotObj->_P = this;
    slotObj->target = data->id;
    auto connection = QObjectPrivate::connect(target,signalIndex,_Q,slotObj,Qt::AutoConnection);
    data->connections << connection;
}

QVariantList QROHost::Private::packAllParentData()
{
    QVariantList ret;
    for(auto i:m_objectDataMap)
    {
        ret << packParentData(this,i->id);
    }

    return ret;
}

void QROHost::Private::onPushParent(RemoteInterfaceSourceImp* src,int target,int parent){
    dispatchParentImp(this,target,parent);
}

void QROHost::Private::onPushParent(QObject* target,QObject* parent)
{
    auto targetId = m_objectIdMap.value(target,NullID);
    auto parentId = m_objectIdMap.value(parent,NullID);

    if(targetId)
    {
        dispatchParentImp(this,targetId,parentId);
    }
}

static void notifyParentChanged(QROHost::Private *_P,ObjectID target,ObjectID parent){
    for(auto i:_P->m_channels)
    {
        i.second->channel->parentUpdate(target,parent);
    }
}

static void onParentChanged(QROHost::Private *_P,ObjectID target)
{
    auto targetData = _P->m_objectDataMap.value(target);
    if(!targetData) return;
    auto targetObj = targetData->obj;
    auto roMeta = QRemoteObject2Meta::Instance()->fetchRemoteClass(targetObj->metaObject()->className());
    auto parentObj = roMeta->hierarchyInterface->parent(targetObj);
    auto parentId = _P->m_objectIdMap.value(parentObj);

    notifyParentChanged(_P,target,parentId);
}

static QVariant packParentData(QROHost::Private* _P,ObjectID id)
{
    auto data = _P->m_objectDataMap[id];
    auto meta = data->obj->metaObject();

    auto roMeta = QRemoteObject2Meta::Instance()->fetchRemoteClass(meta->className());

    //获取该对象的父对象
    auto parent = roMeta->hierarchyInterface->parent(data->obj);
    auto parentId = _P->m_objectIdMap.value(parent,NullID);
    return QVariantList{id,parentId};
}

static void dispatchParentImp(QROHost::Private* _P,ObjectID targetId,ObjectID parentId){
    auto targetData = _P->m_objectDataMap.value(targetId);

    QObject* parentObj = NULL;

    auto parentData = _P->m_objectDataMap.value(parentId);
    if(parentData)
    {
        parentObj = parentData->obj;
    }
    else{
        parentId = NullID;
    }

    if(targetData){
        auto meta = targetData->obj->metaObject();
        auto roMeta = QRemoteObject2Meta::Instance()->fetchRemoteClass(meta->className());
        if(roMeta)
        {
            auto inter = roMeta->hierarchyInterface;
            inter->setParent(targetData->obj,parentObj);
            if(!inter->parentNotifier(targetData->obj))//没有跟踪器的需要主动传播事件
            {
                notifyParentChanged(_P,targetId,parentId);
            }
        }
    }

}
